package com.gjt.serverSocket;

import javaNIO1.customerExeption.NotSupportedException;
import oracle.ucp.logging.annotations.Logging;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Logger;

/**
 * Created with Intel IDEA.
 * 基于通道和选择键的charcgen 服务器
 *
 * @Auther: gjt
 * @Date: 2024/9/21 15:07
 */
public class ChannelChargenServer {
    private static final int DEFAULT_PORT = 80;

    private static Logger logger = Logger.getLogger("channelLog");
    public static void main(String[] args) {
        int port;
        try {
            port = Integer.parseInt(args[0]);
        } catch (RuntimeException e) {
            port = DEFAULT_PORT;
        }

        byte[] rotation = new byte[95 * 2];
        for (byte i = ' '; i <= '~'; i++) {
            rotation[i - ' '] = i;
            rotation[i + 95 - ' '] = i;
        }

        ServerSocketChannel serverChannel;
        Selector selector = null;

        try {
            serverChannel = ServerSocketChannel.open();
            if(!serverChannel.isOpen()){
             logger.warning("请检查通道是否打开");
             return;
            }

            ServerSocket socket = serverChannel.socket();
            socket.bind(new InetSocketAddress(port));

            // 客户端必须检测是否连接成功
//            boolean isConnected = socketChannel.isConnected();
//            if (!isConnected) {
//                System.out.println("没有成功,做别的操作");
//            }


            // 设置非阻塞通道
            if(!serverChannel.isBlocking()){
                serverChannel.configureBlocking(false);

                // 防止socket通道的非阻塞模式被修改，只有拥有此对象的锁的线程才能修改此通道的模式
                serverChannel.blockingLock();
            }


            selector = Selector.open();
            if(!selector.isOpen()){
                logger.warning("请检查选择器是否打开");
                return;
            }

            // 打开一个选择器 把非阻塞服务器通道注册到其中 关心的键 是 接受
            SelectionKey selectionKey = serverChannel.register(selector, SelectionKey.OP_ACCEPT);

            // 获取通道支持的操作的集合
            int ops = serverChannel.validOps();

            // 判断此通道是否支持此操作
            boolean isSupportOperation = (ops & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT;
            if(!isSupportOperation || !selectionKey.isAcceptable()){
                logger.warning("此操作不支持！");
                return;
            }

            Set<SelectionKey> readyKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = readyKeys.iterator();

            while (iterator.hasNext()){
                SelectionKey key = iterator.next();
                iterator.remove();

                try{
                    if(key.isAcceptable()){
                        // 获取此键 关联的已经准备就绪 且 是Accept 的通道
                        ServerSocketChannel channel =(ServerSocketChannel) key.channel();
                        SocketChannel accept = channel.accept();

                        System.out.println("客户端连接成功" + accept.getRemoteAddress());
                        accept.configureBlocking(false);


                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        while (true) {
            try {
                selector.select();
            } catch (IOException e) {
                e.printStackTrace();
                break;
            }


        }
    }
}
